package com.qujia.station.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qujia.common.core.domain.UniversalRedisMessageDto;
import com.qujia.common.core.domain.entity.SysUser;
import com.qujia.common.core.domain.model.LoginUser;
import com.qujia.common.enums.WxConsumptionMessageEnum;
import com.qujia.common.exception.CustomException;
import com.qujia.common.utils.SecurityUtils;
import com.qujia.common.utils.StringUtils;
import com.qujia.coupon.domain.CouponInfo;
import com.qujia.coupon.domain.CouponUser;
import com.qujia.coupon.mapper.CouponInfoMapper;
import com.qujia.coupon.mapper.CouponUserMapper;
import com.qujia.customer.domain.CustomerCardUseRecord;
import com.qujia.customer.domain.CustomerElectronicCard;
import com.qujia.customer.domain.ElectronicCardRefundRecord;
import com.qujia.customer.enums.RefundStatusEnum;
import com.qujia.customer.mapper.ElectronicCardRefundRecordMapper;
import com.qujia.customer.service.ICustomerCardUseRecordService;
import com.qujia.customer.service.ICustomerElectronicCardService;
import com.qujia.integral.domain.CustomerPointsRecord;
import com.qujia.integral.mapper.CustomerPointsRecordMapper;
import com.qujia.station.domain.PayOrder;
import com.qujia.station.domain.PayWay;
import com.qujia.station.domain.PresentCouponUserRecord;
import com.qujia.station.domain.SysAppUserInfo;
import com.qujia.station.mapper.AppUserInfoMapper;
import com.qujia.station.mapper.PayWayMapper;
import com.qujia.station.mapper.PresentCouponUserRecordMapper;
import com.qujia.station.service.IElectronicCardRefundRecordService;
import com.qujia.station.service.IPayOrderService;
import com.qujia.station.service.OrderPrintService;
import com.qujia.system.domain.SysEnterpriseUser;
import com.qujia.system.domain.SysRespon;
import com.qujia.system.service.ISysEnterpriseUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @date 2023/9/8
 */
@Service
public class ElectronicCardRefundRecordServiceImpl extends ServiceImpl<ElectronicCardRefundRecordMapper, ElectronicCardRefundRecord>
        implements IElectronicCardRefundRecordService {

    private static final Logger log = LoggerFactory.getLogger(ElectronicCardRefundRecordServiceImpl.class);

    @Autowired
    private ICustomerCardUseRecordService customerCardUseRecordService;
    @Autowired
    private ICustomerElectronicCardService electronicCardService;
    @Autowired
    private PayWayMapper payWayMapper;
    @Autowired
    private ISysEnterpriseUserService enterpriseUserService;

    @Autowired
    private IPayOrderService payOrderService;

    @Resource
    private OrderPrintService orderPrintService;

    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${message.channel}")
    private String channel;

    @Resource
    private AppUserInfoMapper appUserInfoMapper;

    @Resource
    private CustomerPointsRecordMapper customerPointsRecordMapper;
    @Resource
    private PresentCouponUserRecordMapper presentCouponUserRecordMapper;

    @Resource
    private CouponUserMapper couponUserMapper;

    @Resource
    private CouponInfoMapper couponInfoMapper;

    @Override
    @Transactional
    public Long rechargeRefund(long useRecordId,Long userId){
        LoginUser user;
        if (userId != null) {
            user = new LoginUser();
            SysUser sysUser = new SysUser();
            sysUser.setUserId(userId);
            user.setUser(sysUser);
        }else{
            user = SecurityUtils.getLoginUser();
        }
        log.info("充值退款开始，id:{}",useRecordId);
        CustomerCardUseRecord useRecord = customerCardUseRecordService.selectCustomerCardUseRecordById(useRecordId);
        if (useRecord==null) {
            log.error("充值退款记录未找到，id:{}",useRecordId);
            return null;
        }
        ElectronicCardRefundRecord form = new ElectronicCardRefundRecord();
        //form.setOriginOrderNo(useRecord.getOrderNo());
        form.setRechargeRecordId(useRecord.getId());
        QueryWrapper<ElectronicCardRefundRecord> wrapper = new QueryWrapper<>(form);
        int count = count(wrapper);
        if (count>0) {
            throw new CustomException("订单已提交退款");
        }
        PayWay payWay = payWayMapper.selectPayWayById(useRecord.getPayWayId());
        if (payWay == null) {
            throw new CustomException("支付渠道未找到");
        }
        CustomerElectronicCard card = getUserCard(useRecord);
        if (card == null) {
            throw new CustomException("用户电子卡未找到");
        }
        // 电子卡要减去的金额
//        BigDecimal descBalance = useRecord.getAmt().add(useRecord.getPresentAmt());
//        if (descBalance.compareTo(card.getAmt())>0) {
//            // 要减去的金额大于余额，无法退款
//            throw new CustomException("用户电子卡余额不足，无法退款");
//        }
        // 判断电子卡余额是否大于要退款的金额
        if(card.getAmt().compareTo(useRecord.getAmt())<0 || card.getPresentAmt().compareTo(useRecord.getPresentAmt())<0){
            throw new CustomException("用户电子卡余额不足，无法退款");
        }
        CustomerElectronicCard updateCard = new CustomerElectronicCard();
        updateCard.setId(card.getId());
        updateCard.setRecentlyTime(new Date());
        int i = electronicCardService.incrCustomerElectronicCardBalance(useRecord.getAmt().negate(),useRecord.getPresentAmt().negate(), updateCard);


        if (i==0) {
            log.error("用户余额更新失败，cardId:{}",card.getId());
            throw new CustomException("用户余额更新失败");
        }
        BigDecimal balance = card.getAmt().add(card.getPresentAmt()).subtract(useRecord.getAmt()).subtract(useRecord.getPresentAmt());
        CustomerCardUseRecord refundUseRecord = insertRefundUseRecord(useRecord, balance);
        ElectronicCardRefundRecord refundRecord = new ElectronicCardRefundRecord();
        refundRecord.setOrderNo(refundUseRecord.getOrderNo());
        refundRecord.setOriginOrderNo(useRecord.getOrderNo());
        refundRecord.setRechargeRecordId(useRecord.getId());
        refundRecord.setRefundRecordId(refundUseRecord.getId());
        refundRecord.setPayWayId(payWay.getPayWayId());
        refundRecord.setAmt(useRecord.getAmt());
        refundRecord.setRefundStatus(RefundStatusEnum.PROCESSING);
        refundRecord.setOperateUserId(user.getUser().getUserId());
        //退积分 退优惠券
        refundPresent(useRecord);
        save(refundRecord);
        doRefund(useRecord,refundUseRecord,refundRecord,payWay);


        UniversalRedisMessageDto dto=new UniversalRedisMessageDto();
        dto.setData(JSONObject.toJSONString(useRecord));
        dto.setMessageType(WxConsumptionMessageEnum.CHARGE_REFUND_MESSAGE_PUSH.getValue());
        dto.setTitle(WxConsumptionMessageEnum.CHARGE_REFUND_MESSAGE_PUSH.getKey());
        redisTemplate.convertAndSend(channel, dto);
        return refundUseRecord.getId();
   }

    private void refundPresent(CustomerCardUseRecord useRecord) {
        SysAppUserInfo appUserInfo=new SysAppUserInfo();
        appUserInfo.setMobilePhone(useRecord.getMobilePhone());
        appUserInfo.setStationId(useRecord.getEnterpriseId());
        List<SysAppUserInfo> sysAppUserInfos = appUserInfoMapper.selectList(appUserInfo);
        if(sysAppUserInfos.size()==0){
            return;
        }
        appUserInfo = sysAppUserInfos.get(0);
        CustomerPointsRecord customerPointsRecord=new CustomerPointsRecord();
        customerPointsRecord.setOrderNo(useRecord.getOrderNo());
        customerPointsRecord.setRecordType("+");
        List<CustomerPointsRecord> customerPointsRecords = customerPointsRecordMapper.selectCustomerPointsRecordList(customerPointsRecord);
        if(customerPointsRecords.size()>0){
            //退积分
            customerPointsRecord = customerPointsRecords.get(0);
            Long integral=appUserInfo.getIntegral()-customerPointsRecord.getIntegral();
            if(integral<0){
               // integral=0l;
                throw new CustomException("账户积分不够回退，不能退款");
            }
            appUserInfo.setIntegral(integral);

            customerPointsRecord.setId(null);
            customerPointsRecord.setRecordType("-");
            customerPointsRecord.setCreateTime(new Date());
            customerPointsRecord.setAction("退款");
            customerPointsRecordMapper.insertCustomerPointsRecord(customerPointsRecord);
           // customerPointsRecordService.wxgzhIntegralPush(customerPointsRecord);
        }
        appUserInfoMapper.updateAppUserInfo(appUserInfo);
        //退优惠券
        PresentCouponUserRecord presentCouponUserRecord = new PresentCouponUserRecord();
        presentCouponUserRecord.setOrderNo(useRecord.getOrderNo());
        presentCouponUserRecord.setBusinessName("customer_card_use_record");
        List<PresentCouponUserRecord> couponUserRecords = presentCouponUserRecordMapper.query(presentCouponUserRecord);

        for (PresentCouponUserRecord couponUserRecord : couponUserRecords) {


            CouponUser couponUser = new CouponUser();

            couponUser.setId(couponUserRecord.getCouponUserId().intValue());
            couponUser.setIsDeleted("1");
            couponUserMapper.updateCouponUser(couponUser);
            couponUser = couponUserMapper.selectCouponUserById(couponUserRecord.getCouponUserId().intValue());
            Long couponId = couponUser.getCouponId();
            if(couponUser!=null&&couponUser.getCouponIsUsed().equals("1")){
                throw new CustomException("充值赠送的优惠券已有被使用，不能退款");
            }
            CouponInfo couponInfo = couponInfoMapper.selectCouponInfoById(couponId.intValue());
            //退优惠券次数
            Integer getCouponNum = couponInfo.getGetCouponNum()-1;
            if(getCouponNum<0){
                getCouponNum = 0;
            }
            couponInfo.setGetCouponNum(getCouponNum);
            couponInfoMapper.updateCouponInfo(couponInfo);
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(couponUser.getMobilePhone())&& org.apache.commons.lang3.StringUtils.isNotEmpty(couponUser.getIssueId())){
                int i=couponUserMapper.deleteUserGiveCountByPhoneAndIssueId(couponUser.getMobilePhone(),couponUser.getIssueId());
            }
        }
    }

    private CustomerCardUseRecord insertRefundUseRecord(CustomerCardUseRecord useRecord,BigDecimal balance){
        CustomerCardUseRecord record = new CustomerCardUseRecord();
        record.setOrderNo(StringUtils.generateOrdNo());
        record.setUnionId(useRecord.getUnionId());
        record.setCustomerNo(useRecord.getCustomerNo());
        record.setCustomerName(useRecord.getCustomerName());
        record.setUsageType("-");
        record.setPayType("ref");
        record.setCardOilsType(useRecord.getCardOilsType());
        record.setAmt(useRecord.getAmt());
        record.setPresentAmt(useRecord.getPresentAmt());
        record.setBalance(balance);
        record.setCreateTime(new Date());
        record.setStationId(useRecord.getStationId());
        record.setStationName(useRecord.getStationName());
        record.setStatus("0");
        record.setMobilePhone(useRecord.getMobilePhone());
        record.setEnterpriseId(useRecord.getEnterpriseId());
        record.setServiceCharge(useRecord.getServiceCharge());
        record.setPayWayId(useRecord.getPayWayId());
        customerCardUseRecordService.insertCustomerCardUseRecord(record);
        return record;
    }

    private CustomerElectronicCard getUserCard(CustomerCardUseRecord useRecord) {
        SysEnterpriseUser enterprise = enterpriseUserService.selectSysEnterpriseUserById(useRecord.getEnterpriseId());
        List<CustomerElectronicCard> cardList;
        if (StringUtils.equals("1", enterprise.getCardUseRangeFlag())) {
            cardList = electronicCardService.getCustomerElectronicCardListForEnterprise(useRecord.getMobilePhone(), new String[]{useRecord.getCardOilsType()}, useRecord.getEnterpriseId());
        } else {
            cardList = electronicCardService.getCustomerElectronicCardListForStation(useRecord.getMobilePhone(), new String[]{useRecord.getCardOilsType()}, useRecord.getStationId().longValue());
        }
        if (cardList.isEmpty()) {
            return null;
        }
        return cardList.get(0);
    }

    private void doRefund(CustomerCardUseRecord useRecord,CustomerCardUseRecord refundUseRecord,ElectronicCardRefundRecord refundRecord,PayWay payWay){
        SysRespon sysRespon;
        String thirdOrderNo= null;
        String thirdPayNo = null;
        String payType = payWay.getPayType();
        switch (payType){
            case "1":  //随行付
                sysRespon = sxfRefund(refundRecord, payWay);
                if (sysRespon != null) {
                    if (sysRespon.getData() != null) {
                        HashMap<String, Object> data = (HashMap<String, Object>) sysRespon.getData();
                        thirdOrderNo = (String) data.get("uuid");
                    }
                    String code = sysRespon.getResponCode();
                    if (StringUtils.equalsAny(code,"0000","2002")) {
                        callBackForRefundSuccess(refundRecord,refundUseRecord,thirdOrderNo,thirdPayNo,LocalDateTime.now());
                    }else {
                        sysRespon = null;
                    }
                }
                break;
            case "5":  // 云化支付
                sysRespon = yunhuaRefund(useRecord, refundRecord, payWay);
                if (sysRespon != null) {
                    if (sysRespon.getData() != null) {
                        JSONObject data = (JSONObject) sysRespon.getData();
                        thirdOrderNo = data.getString("refundTransInfoNo");
                        thirdPayNo = data.getString("refundTransPayNo");
                    }
                    if (StringUtils.equals("0000",sysRespon.getResponCode())) {
                        callBackForRefundSuccess(refundRecord,refundUseRecord,thirdOrderNo,thirdPayNo,LocalDateTime.now());
                    }else{
                        sysRespon = null;
                    }
                }
                break;
            default:
                throw new CustomException("不支持的支付渠道");
        }
        if (sysRespon == null) {
            //callBackForRefundFail(refundRecord,thirdOrderNo,thirdPayNo);
            log.error("退款失败");
            throw new CustomException("退款失败");
        }
    }

    private SysRespon sxfRefund(ElectronicCardRefundRecord refundRecord, PayWay payWay){
        try {
            return payOrderService.sendSxfRefundOrder(refundRecord.getAmt(), refundRecord.getOrderNo(),refundRecord.getOriginOrderNo(), payWay.getMno());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private SysRespon yunhuaRefund(CustomerCardUseRecord useRecord, ElectronicCardRefundRecord refundRecord, PayWay payWay){
        try {
            PayOrder payOrder = new PayOrder();
            payOrder.setAmt(refundRecord.getAmt());
            payOrder.setReceivedAmt(refundRecord.getAmt());
            payOrder.setOrderNo(refundRecord.getOriginOrderNo());
            payOrder.setMerchantsNumber(useRecord.getMerchantsNumber());
            payOrder.setTransactionId(useRecord.getTransactionId());
            payOrder.setPayWayId(useRecord.getPayWayId());
            payOrder.setStationId(useRecord.getStationId().longValue());
            payOrder.setPayDate(useRecord.getCreateTime());
            return payOrderService.yunHuaRefundV2(refundRecord.getOrderNo(),payOrder, payWay);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    private void callBackForRefundSuccess(ElectronicCardRefundRecord refundRecorde,CustomerCardUseRecord refundUseRecord,String thirdOrderNo,String thirdPayNo, LocalDateTime refundTime){
        log.info("充值退款成功回调，refundOrderNo:{}",refundRecorde.getOrderNo());
        refundRecorde.setRefundStatus(RefundStatusEnum.SUCCESS);
        refundRecorde.setRefundTime(refundTime);
        refundRecorde.setThirdOrderNo(thirdOrderNo);
        refundRecorde.setThirdPayNo(thirdPayNo);
        updateById(refundRecorde);
        //CustomerCardUseRecord refundUseRecord = customerCardUseRecordService.selectCustomerCardUseRecordById(refundRecorde.getRefundRecordId());
        refundUseRecord.setStatus("1");
        refundUseRecord.setTransactionId(thirdPayNo);
        refundUseRecord.setMerchantsNumber(thirdOrderNo);
        customerCardUseRecordService.updateCustomerCardUseRecord(refundUseRecord);
        log.info("充值退款成功回调-成功，refundOrderNo:{}",refundRecorde.getOrderNo());
        //退款打印小票
        orderPrintService.printRefundElectrondOrder(refundUseRecord,refundRecorde);

    }

    private void callBackForRefundFail(ElectronicCardRefundRecord refundRecorde,String thirdOrderNo,String thirdPayNo) {
        log.info("充值退款失败回调，refundOrderNo:{}",refundRecorde.getOrderNo());
        refundRecorde.setRefundStatus(RefundStatusEnum.FAIL);
        refundRecorde.setThirdOrderNo(thirdOrderNo);
        refundRecorde.setThirdPayNo(thirdPayNo);
        updateById(refundRecorde);
        CustomerCardUseRecord refundUseRecord = customerCardUseRecordService.selectCustomerCardUseRecordById(refundRecorde.getRefundRecordId());
        if (refundUseRecord != null) {
//            rechargeRecord.setStatus(RefundStatusEnum.FAIL.getValue().toString());
//            customerCardUseRecordService.updateCustomerCardUseRecord(rechargeRecord);
            CustomerElectronicCard card = getUserCard(refundUseRecord);
            if (card != null) {
                CustomerElectronicCard updateCard = new CustomerElectronicCard();
                updateCard.setId(card.getId());
                updateCard.setRecentlyTime(new Date());
                electronicCardService.incrCustomerElectronicCardBalance(refundUseRecord.getAmt(),refundUseRecord.getPresentAmt(),updateCard);
            }
        }
        log.info("充值退款成功回调，refundOrderNo:{}",refundRecorde.getOrderNo());
    }

    private ElectronicCardRefundRecord getRefundRecordWithProcessingStatus(String refundOrderNo) {
        ElectronicCardRefundRecord refundRecord = new ElectronicCardRefundRecord();
        refundRecord.setOrderNo(refundOrderNo);
        QueryWrapper<ElectronicCardRefundRecord> wrapper = new QueryWrapper<>(refundRecord);
        ElectronicCardRefundRecord one = getOne(wrapper);
        if (one == null) {
            log.error("退款单号未找到记录，refundOrderNo:{}",refundOrderNo);
            return null;
        }
        if (one.getRefundStatus() != RefundStatusEnum.PROCESSING) {
            log.error("退款记录状态不对，refundOrderNo:{}",refundOrderNo);
            return null;
        }
        return one;
    }


}
